#ifndef MMU_H_
#define MMU_H_

#include "types.h"

/*********************************************************************************************************
  内核 mmu 页面标志
*********************************************************************************************************/

#define MMU_FLAG_VALID   (1 << 0)
#define MMU_FLAG_KACCESS (1 << 1)
#define MMU_FLAG_UACCESS (1 << 2)
#define MMU_FLAG_READ    (1 << 3)
#define MMU_FLAG_WRITE   (1 << 4)
#define MMU_FLAG_EXEC    (1 << 5)
#define MMU_FLAG_CACHE   (1 << 6)
#define MMU_FLAG_DEVICE  (1 << 7)

#define VMM_FLAG_NONE    (0)
#define VMM_FLAG_KTEXT   (MMU_FLAG_VALID | MMU_FLAG_KACCESS | MMU_FLAG_EXEC | MMU_FLAG_CACHE)
#define VMM_FLAG_UTEXT   (MMU_FLAG_VALID | MMU_FLAG_KACCESS | MMU_FLAG_UACCESS | MMU_FLAG_READ | MMU_FLAG_EXEC | MMU_FLAG_CACHE)
#define VMM_FLAG_KDATA   (MMU_FLAG_VALID | MMU_FLAG_KACCESS | MMU_FLAG_READ | MMU_FLAG_WRITE | MMU_FLAG_CACHE)
#define VMM_FLAG_UDATA   (MMU_FLAG_VALID | MMU_FLAG_KACCESS | MMU_FLAG_UACCESS | MMU_FLAG_READ | MMU_FLAG_WRITE | MMU_FLAG_CACHE)
#define VMM_FLAG_UNCACHE (MMU_FLAG_VALID | MMU_FLAG_KACCESS | MMU_FLAG_READ | MMU_FLAG_WRITE)
#define VMM_FLAG_DEVICE  (MMU_FLAG_VALID | MMU_FLAG_KACCESS | MMU_FLAG_READ | MMU_FLAG_WRITE | MMU_FLAG_DEVICE)

/*********************************************************************************************************
  RISCV mmu 页面标志
*********************************************************************************************************/

#define RV_MMU_VALID    (1 << 0)
#define RV_MMU_READ     (1 << 1)
#define RV_MMU_WRITE    (1 << 2)
#define RV_MMU_EXEC     (1 << 3)
#define RV_MMU_USER     (1 << 4)
#define RV_MMU_GLOBAL   (1 << 5)
#define RV_MMU_ACCESS   (1 << 6)
#define RV_MMU_DIRTY    (1 << 7)
#define RV_MMU_BUFFER   (1ul << 61)
#define RV_MMU_CACHE    (1ul << 62)
#define RV_MMU_SO       (1ul << 63)

/*********************************************************************************************************
  RISCV 处理器 Cacheline 大小
*********************************************************************************************************/

#define CONFIG_SYS_CACHELINE_SIZE 64

/*********************************************************************************************************
  RISCV 处理器 PAGE 相关定义
*********************************************************************************************************/

#define PAGE_SIZE  4096
#define PAGE_SHIFT 12

#define PAGE_ROUNDUP(sz)   (((sz)+PAGE_SIZE-1) & ~(PAGE_SIZE-1))
#define PAGE_ROUNDDOWN(a)  (((a)) & ~(PAGE_SIZE-1))

#define PA2PTE(pa)         ((((u64)pa) >> PAGE_SHIFT) << 10) // 物理地址转换为页表项
#define PTE2PA(pte)        ((((pte) >> 10) & 0x07ffffff) << PAGE_SHIFT) // 页表项转换为物理地址

#define VPN_MASK           (0x1FF) // 每个VPN占用9bits
#define VPN_SHIFT(level)   (PAGE_SHIFT+(9*(level))) // 计算VPN移位位数
#define VPN_GET(level, va) ((((u64) (va)) >> VPN_SHIFT(level)) & VPN_MASK) // 计算VPN值

#define SATP_SV39            (8L << 60)
#define MAKE_SATP(pagetable) (SATP_SV39 | (((u64)pagetable) >> 12))

#define MAXVA ((1L << (9 + 9 + 9 + 12)) - 1)

/*********************************************************************************************************
  MMU 相关类型定义
*********************************************************************************************************/
typedef u64   pte_t;
typedef u64  *pagetable_t;

/*********************************************************************************************************
  MMU 接口
*********************************************************************************************************/

int os_mmu_page_map(pagetable_t pagetable, u64 va, u64 pa, u64 size, u32 flag);
void os_mmu_init(void);
void mmu_test(void);
void mmu_kdebug(u64 va);

#endif /* MMU_H_ */